package com.dy.yunying.biz.service.manage.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dy.yunying.api.dto.ChannelManageDto;
import com.dy.yunying.api.entity.*;
import com.dy.yunying.api.req.AdMonitorReq;
import com.dy.yunying.api.req.GameChannelPackReq;
import com.dy.yunying.api.vo.AdvertiserMonitorVO;
import com.dy.yunying.api.vo.ChannelManageVo;
import com.dy.yunying.api.vo.WanChannelPackVO;
import com.dy.yunying.api.vo.WanGameVersionVO;
import com.dy.yunying.biz.config.BdConfig;
import com.dy.yunying.biz.config.KsConfig;
import com.dy.yunying.biz.config.YunYingProperties;
import com.dy.yunying.biz.dao.clickhouse3399.ToutiaoClickMapper;
import com.dy.yunying.biz.dao.manage.ext.AdvertiserMonitorInfoDOMapperExt;
import com.dy.yunying.biz.dao.manage.ext.ChannelManageDOMapperExt;
import com.dy.yunying.biz.service.ads.AdAssetsService;
import com.dy.yunying.biz.service.manage.*;
import com.dy.yunying.biz.utils.DateUtils;
import com.pig4cloud.pig.admin.api.entity.SysDictItem;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.feign.RemoteDictService;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.admin.api.vo.UserSelectVO;
import com.pig4cloud.pig.api.entity.*;
import com.pig4cloud.pig.api.feign.RemoteAccountService;
import com.pig4cloud.pig.api.feign.RemoteConvertService;
import com.pig4cloud.pig.api.vo.AdAccountVo;
import com.pig4cloud.pig.api.vo.AdConvertReq;
import com.pig4cloud.pig.api.vo.SelectConvertTrackReq;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cx
 * @version 1.0.0
 * @ClassName AdConvertServiceImpl.java
 * @createTime 2021年06月02日 14:00:00
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class AdvertiseMonitorServiceImpl implements AdvertiseMonitorService {
	@Autowired
	private GameService gameService;
	@Autowired
	private AdvertiserMonitorInfoDOMapperExt mapper;
	@Autowired
	private GameVersionService gameVersionService;
	@Autowired
	private GameChannelPackService gameChannelPackService;
	@Autowired
	private ChannelManageService channelManageService;
	@Autowired
	private GameChannelPlatformService gameChannelPlatformService;
	@Autowired
	private RemoteConvertService remoteConvertService;
	@Autowired
	private ChannelManageDOMapperExt channelManageDOMapperExt;
	@Autowired
	private RemoteUserService remoteUserService;
	@Autowired
	private RemoteAccountService remoteAccountService;

	private final AdRoleUserService adRoleUserService;

	private final TtExtendPackageService ttExtendPackageService;

	private final AdAssetsService adAssetsService;

	private final ToutiaoClickMapper toutiaoClickMapper;

	private final RemoteDictService remoteDictService;

	private final YunYingProperties yunYingProperties;

	@Value("${pack.app_file_url_root}")
	private String app_file_url_root;

	@Override
	public R page(AdMonitorReq req) {
		List<UserSelectVO> userList = adRoleUserService.getOwnerRoleUsers();
		List<Integer> userIdList = userList.stream().map(UserSelectVO::getUserId).collect(Collectors.toList());
		req.setUserList(userIdList);
		if (StringUtils.isNotBlank(req.getAdvertiserIdArr())) {
			req.setAdvertiserIdArr("'" + req.getAdvertiserIdArr().replace(",", "','") + "'");
		}
		if (StringUtils.isNotBlank(req.getParentchlArr())) {
			req.setParentchlArr("'" + req.getParentchlArr().replace(",", "','") + "'");
		}
		IPage<AdvertiserMonitorVO> page = mapper.page(req);

		if (page != null && CollectionUtils.isNotEmpty(page.getRecords())) {
			List<AdAccount> adAccountList = remoteAccountService.getAllList(new AdAccountVo(), SecurityConstants.FROM_IN);
			R<List<SysUser>> r = remoteUserService.getUserList(SecurityConstants.FROM_IN);
			Map<String, String> map = new HashMap<>();
			if (r.getCode() == CommonConstants.SUCCESS) {
				List<SysUser> list = r.getData();
				map = list.stream().collect(Collectors.toMap(o -> {
					return String.valueOf(o.getUserId());
				}, SysUser::getRealName));
			}

			Map<String, String> accountMap = new HashMap<>();

			if (Objects.nonNull(adAccountList) && adAccountList.size() > 0) {
				accountMap = adAccountList.stream().collect(Collectors.toMap(AdAccount::getAdvertiserId, AdAccount::getAdvertiserName, (v1 , v2) -> v2));
			}
			List<AdvertiserMonitorVO> monitorList = page.getRecords();

			List<Long> adIds = monitorList.stream().map(AdvertiserMonitorVO::getAdid).collect(Collectors.toList());
			// 获取 convert_track 转化三方状态列表
			R<List<ConvertTrack>> resultConvertTrackList = remoteConvertService.selectListByKey(new SelectConvertTrackReq().setAdIds(adIds), SecurityConstants.FROM_IN);
			// 获取 ad_convert 表同步状态
			R<List<AdConvert>> resultAdConvertList = remoteConvertService.getAdConvertListInner(new AdConvertReq().setAdIds(adIds), SecurityConstants.FROM_IN);

			for (AdvertiserMonitorVO advertiserMonitorVO : monitorList) {
				String advertiser = String.valueOf(advertiserMonitorVO.getAdvertiser());
				String advertiserId = advertiserMonitorVO.getAdvertiserId();
				// 翻译投放人名称
				advertiserMonitorVO.setAdvertiserName(map.get(advertiser) == null ? advertiser : map.get(advertiser));

				// 翻译广告账户名称
				advertiserMonitorVO.setAdAccountName(StringUtils.isBlank(advertiserId) ? advertiserId : accountMap.get(advertiserId));

				// 翻译convert_track三方转化ID
				List<ConvertTrack> convertTrackList = resultConvertTrackList.getData();
				if (CollectionUtils.isNotEmpty(convertTrackList)){
					for (ConvertTrack convertTrack : convertTrackList){
						if (Long.valueOf(convertTrack.getMonitorId()).equals(advertiserMonitorVO.getAdid())){
							advertiserMonitorVO.setIdAdPlatform(convertTrack.getIdAdPlatform());
							advertiserMonitorVO.setConvertStatus(String.valueOf(convertTrack.getSyncStatus()));
						}
					}
				}
				// ad_convert 表同步状态
				List<AdConvert> adConvertList = resultAdConvertList.getData();
				if (CollectionUtils.isNotEmpty(adConvertList)){
					for (AdConvert adConvert : adConvertList){
						if (adConvert.getAdId().equals(advertiserMonitorVO.getAdid())){
							advertiserMonitorVO.setIdAdPlatform(adConvert.getConvertId());
							if (PlatformTypeEnum.GDT.getValue().equals(adConvert.getMediaCode())) {
								advertiserMonitorVO.setConvertStatus(adConvert.getStatus().equals(AdConvert.Status.ACCESS_STATUS_COMPLETED) ? "1" : "0");
							}else if(PlatformTypeEnum.KS.getValue().equals(adConvert.getMediaCode())){
								// 快手状态
							}
						}
					}
				}
				if (StringUtils.isBlank(advertiserMonitorVO.getXtMonitorUrl())) {
					advertiserMonitorVO.setXtMonitorUrl(null);
				}
			}
		}
		return R.ok(page);
	}

	/**
	 * 插入一条广告 并打包
	 */
	@Override
	public R insertAndPack(AdvertiserMonitorInfoDO record) {
		final Integer userId = SecurityUtils.getUser().getId();
		//插入时，自动生产id
		record.setAdid(null);
		record.setIsdelete(0);
		record.setIscopy(0);
		record.setUpdatetime(new Date());
		//当前时间为开始打包时间
		record.setPacktime(new Date());
		//设置为正在打包
		record.setPackState(1);
		record.setAppChl("");
		record.setAgentid(-1);
		Long packId = record.getPackId();
		Integer packType = 1;
		if (packId != null && packId > 0) {
			packType = 2;
		}
		record.setPackType(packType);

		if (record.getGid() == null) {
			record.setGid(gidByChildGid(record.getChildGid()));
		}
		// 获取主渠道信息
		ChannelManageVo channelVO = channelManageService.selectParentChlByCode(record.getChl());
		if (Objects.isNull(channelVO)) {
			return R.failed("未获取到主渠道信息");
		}

		ChannelManageDto channel = new ChannelManageDto();
		channel.setPackUserid(userId);
		channel.setPid(channelVO.getId());
		// 根据父渠道ID 获取子渠道编码
		ChannelManageVo channelManageVo = channelManageDOMapperExt.querySonChlBylist(channel);
		if (Objects.isNull(channelManageVo)) {
			return R.failed("未获取到子渠道信息");
		}
		record.setChildChl(channelManageVo.getChncode());
		// 保存数据
		this.save(record);

		// 是否需要生成分包
		if (packType == 1) {
			Thread th = new Thread() {
				@Override
				public void run() {
					log.info(">>> began to pack...");
					WanChannelPackVO packVo = null;
					try {
						//调用打包接口 获取 downloadURL、monitorURL
						packVo = gameChannelPackService.pack(record.getAdid(), userId, record.getAppType());
						record.setDownloadUrl(packVo.getAdUrl());
						record.setMonitorUrl(packVo.getDetectionUrl());
						record.setDisplayMonitorUrl(packVo.getDisplayMonitorUrl());
						record.setPackId(packVo.getPackId());
						record.setPackState(2);     //设置为打包成功
						record.setAppChl(packVo.getCode());       //分包渠道
						record.setXtMonitorUrl(packVo.getXtMonitorUrl());
						log.info(String.format("downloadUrl:[%s], detectionUrl:[%s]", packVo.getAdUrl(), packVo.getDetectionUrl() == null ? "null" : ""));

						//将 打包信息 落地到db
						mapper.updateByPrimaryKeySelective(record);
					} catch (Exception e) {
						log.error("AdvertiseService.insertAndPack :" + e.getMessage());

						//将 打包失败信息 落地到db
						record.setPackState(3);     //设置为打包失败
						update(record);
					}
				}
			};
			th.start();
		} else {
			// ChannelManageVo channelVO = channelManageService.selectParentChlByCode(record.getChl());
			WanChannelPackVO wanChannelPackVO = gameChannelPackService.getVOByPK(packId);
			String detectionUrl = gameChannelPackService.getDetectionUrl(record, wanChannelPackVO, channelManageVo);
			String displayTrackUrl = gameChannelPackService.getDisplayTrackUrl(record, wanChannelPackVO, channelManageVo);
			String xtMonitorUrl = gameChannelPackService.getXtMonitorUrl(record, wanChannelPackVO, channelManageVo);
			AdvertiserMonitorInfoDO tmp = new AdvertiserMonitorInfoDO();
			tmp.setAdid(record.getAdid());
			tmp.setDownloadUrl(wanChannelPackVO.getAdUrl());
			tmp.setMonitorUrl(detectionUrl);
			tmp.setDisplayMonitorUrl(displayTrackUrl);
			tmp.setXtMonitorUrl(xtMonitorUrl);
			//设置为打包成功
			tmp.setPackState(2);
			//分包渠道
			tmp.setAppChl(wanChannelPackVO.getCode());
			update(tmp);
		}

		if (PlatformTypeEnum.TT.getValue().equals(record.getPlatformId())) {
			// 头条 调用投放平台接口，创建转化跟踪
//			R result = this.createConvertTrack(record);
			R result = this.createEventTrackUrl(record);
//			R result = R.ok(); // TODO 测试使用
			if (0 == result.getCode()) {
				AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorInfoDO();
				statusParams.setAdid(record.getAdid());
				statusParams.setConvertStatus("1");
				//修改同步结果
				mapper.updateByPrimaryKeySelective(statusParams);
				return R.ok("创建成功");
			}
			// 创建失败删除记录
			mapper.deleteByPrimaryKey(record.getAdid());
			return R.failed(result.getMsg());
		} else if (PlatformTypeEnum.GDT.getValue().equals(record.getPlatformId())) {
			//获取广告完整信息
			AdvertiserMonitorInfoDO fullRecord = selectByPrimaryKey(record.getAdid());
			if (Objects.isNull(fullRecord)){
				return R.failed("未获取到联调转化信息");
			}

			// 应用信息
			WanGameChannelPlatformDO plantformDo = gameChannelPlatformService.getByPlatformAndGameid(Integer.valueOf(PlatformTypeEnum.GDT.getValue()), fullRecord.getChildGid().intValue(), null);
			if (Objects.isNull(plantformDo) || Objects.isNull(plantformDo.getGdtAppid())) {
				log.error("未找到对应的广点通应用APPID");
				return R.failed("未找到对应的广点通应用APPID");
			}

			fullRecord.setClaimType(record.getClaimType());
			fullRecord.setConversionScene(record.getConversionScene());
			// 创建广点通转化归因
			R resultConversions = this.createGdtConversions(fullRecord, plantformDo);
			if (0 == resultConversions.getCode()){
				AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorInfoDO();
				statusParams.setAdid(record.getAdid());
				statusParams.setConvertStatus("1");
				//修改同步结果
				mapper.updateByPrimaryKeySelective(statusParams);
				return resultConversions;
			}else{
				// 创建失败删除记录
				mapper.deleteByPrimaryKey(record.getAdid());
				return R.failed(resultConversions.getMsg());
			}
		} else if (PlatformTypeEnum.KS.getValue().equals(record.getPlatformId())) {
			R result = this.createKsApp(record);
			if (0 == result.getCode()){
				return R.ok("创建成功");
			}
			// 创建失败删除记录
			mapper.deleteByPrimaryKey(record.getAdid());
			return R.failed(result.getMsg());
		} else if (PlatformTypeEnum.BD.getValue().equals(record.getPlatformId())) {
			R result = this.addOcpcTransFeed(record);
			if (0 == result.getCode()){
				return R.ok("创建成功");
			}
			// 创建失败删除记录
			mapper.deleteByPrimaryKey(record.getAdid());
			return R.failed(result.getMsg());
		} else {
			return R.failed("无效的平台ID");
		}
	}

	public R addOcpcTransFeed(AdvertiserMonitorInfoDO record){
		//获取广告完整信息
		AdvertiserMonitorInfoDO fullRecord = selectByPrimaryKey(record.getAdid());
		if (Objects.isNull(fullRecord)){
			return R.failed("未获取到转化信息");
		}
		// 获取子游戏信息
		WanGameDO childGame = gameService.selectByPrimaryKey(fullRecord.getChildGid());
		if (Objects.isNull(childGame)){
			return R.failed("未获取到子游戏信息");
		}
		// 应用信息
		WanGameChannelPlatformDO plantformDo = gameChannelPlatformService.getByPlatformAndGameid(Integer.valueOf(PlatformTypeEnum.BD.getValue()), fullRecord.getChildGid().intValue(), null);
		if (Objects.isNull(plantformDo) || Objects.isNull(plantformDo.getGdtAppid())) {
			log.error("未找到对应的广点通应用APPID");
			return R.failed("未找到对应的广点通应用APPID");
		}
		String packDomain = app_file_url_root.replace("/pack", "");
		AdConvertReq adConvert = new AdConvertReq();
		adConvert.setAdId(fullRecord.getAdid());
		adConvert.setPgameId(String.valueOf(fullRecord.getGid()));
		adConvert.setGameId(String.valueOf(fullRecord.getChildGid()));
		adConvert.setChl(fullRecord.getChl());
		adConvert.setMediaCode(PlatformTypeEnum.BD.getValue());
		adConvert.setAdvertiserId(fullRecord.getAdvertiserId());
		adConvert.setConvertName(fullRecord.getAdname());
		adConvert.setDownloadUrl(packDomain + fullRecord.getDownloadUrl());
		adConvert.setActionTrackUrl(this.getMonitorUrl(fullRecord, null));
		adConvert.setPackageName(childGame.getPkName());
		adConvert.setAppId(String.valueOf(plantformDo.getAppid()));
		adConvert.setAppName(plantformDo.getGdtAppid());
		adConvert.setConvertTarget(fullRecord.getConvertType());
		adConvert.setDeepConversionType(fullRecord.getDeepExternalAction());
		log.info(">>>创建百度转化params:" + JSON.toJSONString(adConvert));
		R<AdConvert> result = remoteConvertService.addOcpcTransFeed(adConvert, SecurityConstants.FROM_IN);
		log.info(">>>创建百度转化result:" + JSON.toJSONString(result));
		if (Objects.nonNull(result) && 0 == result.getCode()){
			AdConvert convert = result.getData();
			AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorVO();
			statusParams.setAdid(record.getAdid());
			statusParams.setConvertStatus("1");
			statusParams.setMonitorUrl(this.getMonitorUrl(fullRecord, null));
			//修改同步结果
			mapper.updateByPrimaryKeySelective(statusParams);
			return R.ok("创建成功");
		}
		return result;
	}
	/**
	 * 调用头条 - 创建监测组链接
	 * @param record
	 * @return
	 */
	public R createEventTrackUrl(AdvertiserMonitorInfoDO record){
		//获取广告完整信息
		AdvertiserMonitorInfoDO fullRecord = selectByPrimaryKey(record.getAdid());
		// 获取下载链接地址
		TtExtendPackageDO ttExtendPackageDO = ttExtendPackageService.getOne(Wrappers.<TtExtendPackageDO>lambdaQuery()
				// 分包表存的广告账户是创建应用的广告账户，创建监测链接组获取下载地址不能带广告账户条件
//				.eq(TtExtendPackageDO::getAdvertiserId,fullRecord.getAdvertiserId())
				.eq(TtExtendPackageDO::getChannelId,fullRecord.getAppChl())
				.eq(TtExtendPackageDO::getGameid,fullRecord.getChildGid())
				.eq(TtExtendPackageDO::getPlatform,PlatformTypeEnum.TT.getValue())
				.eq(TtExtendPackageDO::getStatus,"PUBLISHED")
				.eq(TtExtendPackageDO::getIsDeleted,0)
				.last("LIMIT 1"));
		if (Objects.isNull(ttExtendPackageDO)) {
			log.error("未获取到下载链接地址");
			return R.failed("分包未发布,请稍后再试");
		}
		AdAssets adAssets = adAssetsService.getOne(Wrappers.<AdAssets>lambdaQuery()
				.eq(AdAssets::getAdvertiserId,fullRecord.getAdvertiserId())
				.eq(AdAssets::getAppCloudId,ttExtendPackageDO.getAppId())
				.eq(AdAssets::getDeleted,0).last("LIMIT 1"));
		if (Objects.isNull(adAssets)) {
			log.error("未获取到资产信息");
			return R.failed("应用下没有资产,请先创建");
		}
		AdAssetsTrack adAssetsTrack = new AdAssetsTrack();
		adAssetsTrack.setAdvertiserId(adAssets.getAdvertiserId());
		adAssetsTrack.setAssetId(adAssets.getAssetId());
		adAssetsTrack.setDownloadUrl(ttExtendPackageDO.getDownloadUrl());
		adAssetsTrack.setActionTrackUrl(fullRecord.getMonitorUrl());
		adAssetsTrack.setTrackUrlGroupName(fullRecord.getAdname());
		adAssetsTrack.setPackageName(adAssets.getPackageName());
		adAssetsTrack.setAppCloudId(Long.valueOf(adAssets.getAppCloudId()));
		adAssetsTrack.setAppName(adAssets.getAppName());
		adAssetsTrack.setPgameId(fullRecord.getGid());
		adAssetsTrack.setGameId(fullRecord.getChildGid());
		adAssetsTrack.setChl(fullRecord.getAppChl());
		adAssetsTrack.setAdId(fullRecord.getAdid());
		adAssetsTrack.setCreateId(SecurityUtils.getUser().getId().longValue());
		log.info(">>>>>>创建监测组链接params:{}",JSON.toJSONString(adAssetsTrack));
		R<AdAssetsTrack> result = remoteConvertService.createEventTrackUrl(adAssetsTrack, SecurityConstants.FROM_IN);
		log.info(">>>>>>创建监测组链接result:{}",JSON.toJSONString(result));
		return result;
	}

	//调用投放平台接口，创建转化跟踪
	private R createConvertTrack(AdvertiserMonitorInfoDO record) {

		try {
			//获取广告完整信息
			AdvertiserMonitorInfoDO fullRecord = selectByPrimaryKey(record.getAdid());

			ChannelManageVo channelVO = channelManageService.selectChildChlByCode(fullRecord.getChildChl());
			WanGameChannelPlatformDO plantformDo = gameChannelPlatformService.getByPlatformAndGameid(channelVO.getPlatform(), fullRecord.getChildGid().intValue(), null);
			if (plantformDo == null) {
				log.error("AdvertiseService.insertAndPack.plantformDo: 该游戏未找到对应的 appid");
				return R.failed("该游戏未找到对应的 appid");
			}
			QueryWrapper<TtExtendPackageDO> wrapper = new QueryWrapper<>();
			wrapper.eq("channel_id", fullRecord.getAppChl());
			wrapper.eq("is_deleted", 0);
			wrapper.eq("status", "PUBLISHED");
			wrapper.last("LIMIT 1");
			// 获取下载链接地址
			TtExtendPackageDO ttExtendPackageDO = ttExtendPackageService.getOne(wrapper);
			if (Objects.isNull(ttExtendPackageDO)) {
				log.error("未获取到下载链接地址");
				return R.failed("未获取到下载链接地址");
			}

			WanGameDO childGame = gameService.selectByPrimaryKey(fullRecord.getChildGid());
			String packageName = childGame.getPkName();

			String packDomain = app_file_url_root.replace("/pack", "");

			ConvertTrack convertTrack = new ConvertTrack();
			convertTrack.setName(fullRecord.getAdname());
			convertTrack.setAppId(String.valueOf(plantformDo.getAppid()));
			convertTrack.setAdAccount(fullRecord.getAdvertiserId());
			convertTrack.setGameId(fullRecord.getChildGid());
			convertTrack.setPackageName(packageName);
			convertTrack.setConvertType(Short.valueOf(record.getConvertType()));
			if (StringUtils.isNotBlank(fullRecord.getConvertDataType())) {
				convertTrack.setConvertDataType(fullRecord.getConvertDataType());
			}
			if (StringUtils.isNotBlank(record.getDeepExternalAction())) {
				// 深度转化目标
				convertTrack.setDeepExternalAction(Short.valueOf(record.getDeepExternalAction()));
			}
//			convertTrack.setDownloadUrl(String.format("%s/%s", packDomain, fullRecord.getDownloadUrl()));
			convertTrack.setDownloadUrl(ttExtendPackageDO.getDownloadUrl());
			convertTrack.setPlatformId((short) 1);
			if (StringUtils.isNotBlank(fullRecord.getMonitorUrl())) {
				convertTrack.setActionTrackUrl(fullRecord.getMonitorUrl());
			}
			//广告平台，默认 头条
			convertTrack.setAdPlatform(Short.valueOf("1"));
			//同步状态，默认 未同步
			convertTrack.setSyncStatus(Short.valueOf("0"));
			//status 默认 未激活
			convertTrack.setStatus(Short.valueOf("0"));
			//转化来源类型 默认 AD_CONVERT_SOURCE_TYPE_SDK（应用下载SDK）
			convertTrack.setConvertSourceType(Short.valueOf("7"));
			//app_type 默认 APP_ANDROID
			convertTrack.setAppType(Short.valueOf("1"));
			convertTrack.setCreatetime(new Date());
			//目前只支持 头条
			convertTrack.setPlatformId(Short.valueOf("1"));
			convertTrack.setMonitorId(fullRecord.getAdid().intValue());
			convertTrack.setAppChl(fullRecord.getAppChl());
			log.info("AdvertiseService.insertAndPack.params:" + JSON.toJSONString(convertTrack));

			R result = remoteConvertService.create(convertTrack, SecurityConstants.FROM_IN);

			log.info("调用转化跟踪接口.convertTrack:" + result);

			AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorVO();
			if (Objects.nonNull(record.getAdid())) {
				if (result.getCode() == 0) {
					statusParams.setConvertStatus("1");
				} else {
					statusParams.setConvertStatus("2");
				}
				statusParams.setAdid(record.getAdid());
				//修改同步结果
				mapper.updateByPrimaryKeySelective(statusParams);
			}
			return result;
		} catch (Exception e) {
			log.error("AdvertiseService.insertAndPack.convertTrack.exp:", e);
			return R.failed("创建转化异常");
		}
	}

	/**
	 * 广点通上传渠道包
	 * @param fullRecord
	 * @param plantformDo
	 * @return
	 */
	private R gdtChannelPackage(AdvertiserMonitorInfoDO fullRecord, WanGameChannelPlatformDO plantformDo) {
		try {
			Map<String, Object> param = new HashMap<>();
			param.put("packid", fullRecord.getPackId());
			param.put("convertStatus", "1");
			// 验证包名是否被占用
			AdvertiserMonitorInfoDO advertiserMonitorInfoDO = mapper.selectAdMonitor(param);
			if (Objects.nonNull(advertiserMonitorInfoDO)) {
				AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorVO();
				statusParams.setConvertStatus("1");
				statusParams.setAdid(fullRecord.getAdid());
				//修改同步结果
				mapper.updateByPrimaryKeySelective(statusParams);
				return R.ok();
			} else {
				String packDomain = app_file_url_root.replace("/pack", "");
				GdtChannelPackage channelPackage = new GdtChannelPackage();
				channelPackage.setAdId(fullRecord.getAdid());
				channelPackage.setAdAccount(fullRecord.getAdvertiserId());
				channelPackage.setUnionAppId(String.valueOf(plantformDo.getGdtAppid()));
				channelPackage.setPackageName(fullRecord.getAdname());
				channelPackage.setCustomizedChannelId(fullRecord.getAppChl());
				channelPackage.setPackageOriginUrl(String.format("%s/%s", packDomain, fullRecord.getDownloadUrl()));

				log.info("广点通上传渠道包.params:" + JSON.toJSONString(channelPackage));
				R result = remoteConvertService.channelPackage(channelPackage, SecurityConstants.FROM_IN);
				log.info("广点通上传渠道包.result:" + result);

				AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorVO();
				if (Objects.nonNull(fullRecord.getAdid()) && Objects.nonNull(result.getData())) {
					GdtChannelPackage channelPackage1 = JSONObject.parseObject(JSON.toJSONString(result.getData()), GdtChannelPackage.class);
					if (result.getCode() == 0) {
						if ("PACKAGE_STATUS_PENDING".equals(channelPackage1.getPackageStatus())) {
							statusParams.setConvertStatus("3");
						} else if ("PACKAGE_STATUS_NORMAL".equals(channelPackage1.getPackageStatus())) {
							statusParams.setConvertStatus("1");
						} else {
							statusParams.setConvertStatus("4");
						}
					} else {
						statusParams.setConvertStatus("2");
					}
					statusParams.setAdid(fullRecord.getAdid());
					//修改同步结果
					mapper.updateByPrimaryKeySelective(statusParams);
				}

				return result;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return R.ok();
	}

	/**
	 * 远程调用创建广点通转化归因
	 * @param fullRecord
	 * @return
	 */
	public R createGdtConversions(AdvertiserMonitorInfoDO fullRecord, WanGameChannelPlatformDO plantformDo){
		AdConvert adConvert = new AdConvert();
		adConvert.setAdId(fullRecord.getAdid());
		adConvert.setPgameId(fullRecord.getGid());
		adConvert.setGameId(fullRecord.getChildGid());
		adConvert.setChl(fullRecord.getChl());
		adConvert.setMediaCode(PlatformTypeEnum.GDT.getValue());
		adConvert.setAdvertiserId(fullRecord.getAdvertiserId());
		adConvert.setAppId(Long.valueOf(plantformDo.getGdtAppid()));
		adConvert.setConvertName(fullRecord.getAdname());
		adConvert.setConvertTarget(fullRecord.getConvertType());
		adConvert.setDeepConversionType(fullRecord.getDeepExternalAction());
		adConvert.setActionTrackUrl(fullRecord.getMonitorUrl());
		adConvert.setPackageName(fullRecord.getAppChl());
		adConvert.setClaimType(fullRecord.getClaimType());
		adConvert.setConversionScene(fullRecord.getConversionScene());
		log.info(">>>远程调用创建广点通转化归因param:{}",JSON.toJSONString(adConvert));
		R result = remoteConvertService.createGdtConversions(adConvert, SecurityConstants.FROM_IN);
		log.info(">>>远程调用创建广点通转化归因result:{}",JSON.toJSONString(result));
		return result;
	}

	/**
	 * 创建快手应用
	 * @param record
	 * @return
	 */
	public R createKsApp(AdvertiserMonitorInfoDO record){
		// 获取子游戏信息
		WanGameDO childGame = gameService.selectByPrimaryKey(record.getChildGid());
		if (Objects.isNull(childGame)){
			return R.failed("未获取到子游戏信息");
		}
		//获取广告完整信息
		AdvertiserMonitorInfoDO fullRecord = selectByPrimaryKey(record.getAdid());
		if (Objects.isNull(fullRecord)){
			return R.failed("未获取到转化信息");
		}
		String packDomain = app_file_url_root.replace("/pack", "");
		String downloadUrl = String.format("%s/%s", packDomain, fullRecord.getDownloadUrl());
		KsApp ksApp = new KsApp();
		ksApp.setAdvertiserId(fullRecord.getAdvertiserId());
		ksApp.setPgameId(fullRecord.getGid());
		ksApp.setGameId(fullRecord.getChildGid());
		ksApp.setChl(fullRecord.getAppChl());
		ksApp.setAppVersion(fullRecord.getAppChl());
		ksApp.setAppName(childGame.getGname());
		ksApp.setAdId(fullRecord.getAdid());
		// TODO 暂时写死，需要讨论游戏icon获取位置
		ksApp.setImageToken("1f7af96c5a944ad5bdf17357eaaa3a45.jpg");
		ksApp.setPackageName(childGame.getPkName());
		ksApp.setUrl(downloadUrl);
		ksApp.setScanStatus(1);
		log.info("创建快手应用>params:" + JSON.toJSONString(ksApp));
		R<KsApp> result = remoteConvertService.createKsApp(ksApp, SecurityConstants.FROM_IN);
		log.info("创建快手应用>result:" + JSON.toJSONString(result));
		if (Objects.nonNull(result) && 0 == result.getCode()){
			KsApp app = result.getData();
			AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorVO();
			statusParams.setAdid(record.getAdid());
			statusParams.setConvertStatus("1");
			statusParams.setMonitorUrl(this.getMonitorUrl(fullRecord, app.getAppId()));
			//修改同步结果
			mapper.updateByPrimaryKeySelective(statusParams);
			return R.ok("创建成功");
		}else{
			if (Objects.nonNull(result)){
				return R.failed(result.getMsg());
			}
			return R.failed("系统异常");
		}
	}

	public String getMonitorUrl(AdvertiserMonitorInfoDO record, Long ksAppId){
		Map<String, String> params = new HashMap<>();
		params.put("advertId", String.valueOf(record.getAdid()));
		params.put("adaccount", record.getAdvertiserId());
		params.put("gameid", String.valueOf(record.getChildGid()));
		String appchl = record.getAppChl();
		if (StringUtils.isNotBlank(appchl)) {
			appchl = appchl.replaceAll("_", "").replaceAll("-", "");
		}
		params.put("ptype", appchl);
		String template = "";
		if (PlatformTypeEnum.KS.getValue().equals(record.getPlatformId())){
			params.put("ksappid", String.valueOf(ksAppId));
			template = yunYingProperties.getApi_v3_detection_domain() + KsConfig.click_track_url_template;
		}else if(PlatformTypeEnum.BD.getValue().equals(record.getPlatformId())){
			template = yunYingProperties.getApi_v3_detection_domain() + BdConfig.click_track_url_template;
		}
		return StrSubstitutor.replace(template, params);
	}

	@Override
	public boolean batchRepack(String adids) {
		final String creator = String.valueOf(SecurityUtils.getUser().getId());

		//1、将打包状态设置为正在打包
		mapper.uptPackStateByIds(adids);

		//2、调用批量打包接口，更新打包状态
		//开启新的线程，后台执行打包操作
		Thread th = new Thread(new Runnable() {
			@Override
			public void run() {

				List<AdvertiserMonitorInfoDO> adList = mapper.getByPKs(adids);

				// 广告按子游戏、子渠道分组
				Map<String, Map<String, Set<String>>> gameChlAppChlMap = new HashMap<>();
				for (AdvertiserMonitorInfoDO adInfo : adList) {
					Long gameId = adInfo.getChildGid();
					Integer appType = adInfo.getAppType();
					String childChl = adInfo.getChildChl();
					String key = gameId + "_" + appType;

					Map<String, Set<String>> chlAppChlMap = gameChlAppChlMap.computeIfAbsent(key, k -> new HashMap<>());
					// 使用Set去重
					Set<String> appChlSetTmp = chlAppChlMap.computeIfAbsent(childChl, k -> new HashSet<>());
					appChlSetTmp.add(adInfo.getAppChl());
				}

				// 分批打包
				GameChannelPackReq req = new GameChannelPackReq();
				req.setCreator(creator);
				for (Map.Entry<String, Map<String, Set<String>>> gameChlAppChlMapEntry : gameChlAppChlMap.entrySet()) {
					String[] key = gameChlAppChlMapEntry.getKey().split("_");
					Long gameId = Long.valueOf(key[0]);
					Integer appType = Integer.valueOf(key[1]);
					Map<String, Set<String>> chlAppChlMap = gameChlAppChlMapEntry.getValue();
					WanGameVersionVO game = gameService.selectVersionVOByPK(gameId, appType);
					if (game == null) {
						log.error("子游戏包信息缺失, gameId={}", gameId);
						continue;
					}
					Long versionId = game.getVersionId();
					GameVersionDO gameVersion = gameVersionService.getByPK(versionId);
					if (gameVersion == null) {
						log.error("子游戏基础包缺失, versionId={}", versionId);
						continue;
					}
					Map<String, Long> appChlPackIdMap = new HashMap<>();
					for (Map.Entry<String, Set<String>> chlAdIdMapEntry : chlAppChlMap.entrySet()) {
						String childChl = chlAdIdMapEntry.getKey();
						Set<String> appChlSetTmp = chlAdIdMapEntry.getValue();
						ChannelManageVo channelVO = channelManageService.selectChildChlByCode(childChl);
						if (gameVersion == null) {
							log.error("子渠道信息缺失, childChl={}", childChl);
							continue;
						}
						List<String> appChlListTmp = new ArrayList<>(appChlSetTmp);
						List<WanChannelPackVO> packList = gameChannelPackService.batchPackSync(gameVersion, channelVO, appChlListTmp, req);
						if (CollectionUtils.isEmpty(packList)) {
							continue;
						}
						// 更新计划打包结果
						for (WanChannelPackVO packVO : packList) {
							String appChl = packVO.getCode();
							Long packId = packVO.getPackId();
							appChlPackIdMap.put(appChl, packId);
						}

						// 更新计划打包结果
						for (AdvertiserMonitorInfoDO adInfo : adList) {
							String appChl = adInfo.getAppChl();
							Long packId = appChlPackIdMap.get(appChl);
							if (packId != null) {
								AdvertiserMonitorInfoDO tmp = new AdvertiserMonitorInfoDO();
								tmp.setAdid(adInfo.getAdid());
								tmp.setPackId(packId);
								tmp.setPackState(2);     //打包成功
								update(tmp);
							}
						}
					}
					// 打包失败
					for (AdvertiserMonitorInfoDO adInfo : adList) {
						String appChl = adInfo.getAppChl();
						Long packId = appChlPackIdMap.get(appChl);
						if (packId == null) {
							AdvertiserMonitorInfoDO tmp = new AdvertiserMonitorInfoDO();
							tmp.setAdid(adInfo.getAdid());
							tmp.setPackState(3);     //打包失败
							update(tmp);
						}
					}
				}
			}
		});
		th.start();

		return true;
	}

	//根据子游戏id 获取父游戏id
	public Long gidByChildGid(Long childGameId) {
		WanGameDO gameDo = gameService.selectByPrimaryKey(childGameId);
		return gameDo.getPgid();
	}

	/**
	 * 新增
	 *
	 * @param record
	 * @return
	 */
	public int save(AdvertiserMonitorInfoDO record) {
		final Integer userId = SecurityUtils.getUser().getId();
		record.setCreatetime(DateUtils.getCurrentDate());
		//当前登录用户即为投放人
		record.setAdvertiser(userId);
		return mapper.insertSelective(record);
	}

	/**
	 * 更新
	 *
	 * @param record
	 * @return
	 */
	@Override
	public boolean update(AdvertiserMonitorInfoDO record) {
		record.setUpdatetime(DateUtils.getCurrentDate());
		int count = mapper.updateByPrimaryKeySelective(record);

		if (count > 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 按id查询
	 */
	@Override
	public AdvertiserMonitorVO selectByPrimaryKey(Long adid) {
		AdvertiserMonitorInfoDO data = mapper.selectByPrimaryKey(adid);
		AdvertiserMonitorVO vo = new AdvertiserMonitorVO();
		BeanUtils.copyProperties(data, vo);
		//获取渠道名称
		ChannelManageVo childChn = channelManageService.selectChildChlByCode(data.getChildChl());
		if (childChn != null) {
			vo.setChildChlName(childChn.getChnname());
		}
		vo.setAdvertiserName(SecurityUtils.getUser().getUsername());
		return vo;
	}

	//广告名称是否存在
	@Override
	public boolean isAdNameExist(AdvertiserMonitorInfoDO record) {
		List<AdvertiserMonitorInfoDO> adList = mapper.selectByAdName(record);

		if (adList.size() > 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 批量复制
	 *
	 * @param adid
	 * @param batchSize
	 * @return
	 */
	@Override
	public boolean batchCopy(Long adid, int batchSize) {
		if (adid == null || batchSize <= 0) {
			return false;
		}
		final Integer userid = SecurityUtils.getUser().getId();

		AdvertiserMonitorInfoDO record = selectByPrimaryKey(adid);
		String adNamePrefix = getBaseName(record);
		String convertType = record.getConvertType();
		String deepExternalAction = record.getDeepExternalAction();

		List<Long> adidList = new ArrayList<>();

		//生成要插入的序号
		List<AdvertiserMonitorInfoDO> insertList = new ArrayList<>();
		for (int i = 1; i <= batchSize; i++) {
			AdvertiserMonitorInfoDO tmp = new AdvertiserMonitorInfoDO();
			BeanUtils.copyProperties(record, tmp);
			tmp.setAdid(null);       //插入时，自动生产id
			tmp.setMonitorUrl(null);
			tmp.setDisplayMonitorUrl(null);
			tmp.setHisName(adNamePrefix);
			tmp.setIscopy(1);
			tmp.setAdname(String.format("%s_copyed", adNamePrefix));     //先给一个adName占位符，表示该ad为批量复制产生
			tmp.setAgentid(-1);

			tmp.setCreatetime(new Date());
			tmp.setUpdatetime(null);
			tmp.setPacktime(new Date());     //当前时间为开始打包时间
			tmp.setPackState(1);     //设置为正在打包
			tmp.setConvertType(convertType);
			tmp.setPlatformId(record.getPlatformId());
			tmp.setDeepExternalAction(deepExternalAction);
			insertList.add(tmp);
		}
		this.batchInsert(insertList);

		Integer packType = record.getPackType();

		ChannelManageVo channelVO = channelManageService.selectChildChlByCode(record.getChildChl());
		WanChannelPackVO wanChannelPackVO = gameChannelPackService.getVOByPK(record.getPackId());

		// 更新广告名称
		List<AdvertiserMonitorInfoDO> updateList = new ArrayList<>();
		for (AdvertiserMonitorInfoDO insertTmp : insertList) {
			AdvertiserMonitorInfoDO updateTmp = new AdvertiserMonitorInfoDO();
			Long adidTmp = insertTmp.getAdid();
			updateTmp.setAdid(adidTmp);
			updateTmp.setConvertType(convertType);
			updateTmp.setDeepExternalAction(deepExternalAction);
			//拿到 adid 后,立即将adName改为 {复制前adName}_{adid}
			updateTmp.setAdname(String.format("%s_%d", adNamePrefix, adidTmp));
			updateTmp.setPlatformId(insertTmp.getPlatformId());

			// 使用已有分包
			if (packType == 2) {
				String detectionUrl = gameChannelPackService.getDetectionUrl(record, wanChannelPackVO, channelVO);
				updateTmp.setMonitorUrl(detectionUrl);
				String displayTrackUrl = gameChannelPackService.getDisplayTrackUrl(record, wanChannelPackVO, channelVO);
				updateTmp.setDisplayMonitorUrl(displayTrackUrl);
				updateTmp.setPackState(2);     //设置为打包成功
			} else {// 自动生成广告分包
				//将 adid 放入list，用于批量打包
				adidList.add(adidTmp);
			}
			updateList.add(updateTmp);
		}
		this.batchUpdate(updateList);

		if (CollectionUtils.isEmpty(adidList)) {
			//为每个广告创建 转化
			for (AdvertiserMonitorInfoDO item : updateList) {
				if (PlatformTypeEnum.TT.getValue().equals(item.getPlatformId())){
					// 创建监测链接组
					R result = this.createEventTrackUrl(item);
					AdvertiserMonitorInfoDO statusParams = new AdvertiserMonitorInfoDO();
					statusParams.setAdid(item.getAdid());
					if (0 == result.getCode()) {
						statusParams.setConvertStatus("1");
					}else{
						statusParams.setConvertStatus("2");
					}
					//修改同步结果
					mapper.updateByPrimaryKeySelective(statusParams);
				}else if(PlatformTypeEnum.BD.getValue().equals(item.getPlatformId())){
					this.addOcpcTransFeed(item);
				}
			}
			return true;
		}

		// 是否需要生成分包
		if (packType == 1) {
			//开启新的线程，后台执行打包操作
			Thread th = new Thread(new Runnable() {
				@Override
				public void run() {
					//将list分组，优化用户体验
					List<List<Long>> splitedList = splitList(adidList, 10);
					Collections.reverse(splitedList);      //将分组反向 优化用户体验

					//遍历分组后的list
					splitedList.forEach(slist -> {
						//获取游戏版本\子渠道对象 为批量打包做准备
						WanGameVersionVO game = gameService.selectVersionVOByPK(record.getChildGid(), wanChannelPackVO.getPackType());
						GameVersionDO gameVersion = gameVersionService.getByPK(game.getVersionId());
						ChannelManageVo channelVO = channelManageService.selectChildChlByCode(record.getChildChl());

						//批量打包 开始
						try {
							Map<Long, WanChannelPackVO> packInfo = gameChannelPackService.pack(record, gameVersion, channelVO, slist, userid);

							//将打包获取的信息，写入db
							packInfo.forEach((key, value) -> {
								AdvertiserMonitorInfoDO adItem = new AdvertiserMonitorInfoDO();
								adItem.setAdid(key);
								adItem.setDownloadUrl(value.getAdUrl());
								adItem.setMonitorUrl(value.getDetectionUrl());
								adItem.setDisplayMonitorUrl(value.getDisplayMonitorUrl());
								adItem.setPackId(value.getPackId());
								adItem.setPackState(2);     //打包成功
								adItem.setAppChl(value.getCode());          //分包渠道
								update(adItem);

								createConvertTrack(adItem);
							});
						} catch (Exception e) {
							//将打包失败信息同步到db
							slist.forEach(adid1 -> {
								AdvertiserMonitorInfoDO adItem = new AdvertiserMonitorInfoDO();
								adItem.setAdid(adid1);
								adItem.setPackState(3);     //打包失败
								update(adItem);
							});
						}
					});
				}
			});
			th.start();
		}
		return true;
	}

	public boolean batchInsert(List<AdvertiserMonitorInfoDO> list) {
		int flag = mapper.batchInsert(list);
		if (flag > 0) {
			return true;
		} else {
			return false;
		}
	}

	public boolean batchUpdate(List<AdvertiserMonitorInfoDO> list) {
		int flag = mapper.batchUpdate(list);
		if (flag > 0) {
			return true;
		} else {
			return false;
		}
	}

	//批量复制的基准
	private String getBaseName(AdvertiserMonitorInfoDO adv) {

		//若不是批量复制来的广告,直接按照当前名称做批量复制
		if (adv.getIscopy() == Short.parseShort("0") ||
				adv.getHisName() == null) {  //hisName丢失,直接按照当前名称做批量复制
			return adv.getAdname();
		} else {
			//若是批量复制来的广告,看看是否修改过adName
			String nameBeforeChange = String.format("%s_%d", adv.getHisName(), adv.getAdid());
			if (adv.getAdname().equals(nameBeforeChange)) {
				//若没有修改过广告名
				return adv.getHisName();
			} else {
				//若修改了，则用当前adName 来复制
				return adv.getAdname();
			}
		}
	}

	private List<List<Long>> splitList(List<Long> list, int groupSize) {
		int length = list.size();
		// 计算可以分成多少组
		int num = (length + groupSize - 1) / groupSize; // TODO
		List<List<Long>> newList = new ArrayList<>(num);
		for (int i = 0; i < num; i++) {
			// 开始位置
			int fromIndex = i * groupSize;
			// 结束位置
			int toIndex = (i + 1) * groupSize < length ? (i + 1) * groupSize : length;
			newList.add(list.subList(fromIndex, toIndex));
		}
		return newList;
	}

	@Override
	public AdvertiserMonitorInfoDO selectAdMonitor(Map<String, Object> param) {
		return mapper.selectAdMonitor(param);
	}

	@Override
	public R getCallBackUrlByConvertId(String adPlatformId) {
		String callBackUrl = toutiaoClickMapper.getCallBackUrlByConvertId(adPlatformId);
		List<String> resultData = new ArrayList<String>();
		if (StringUtils.isNotBlank(callBackUrl)) {
			R<List<SysDictItem>> remoteData = remoteDictService.getDictByType4Inner(SecurityConstants.FROM_IN, "tt_check_event_type");
			if (remoteData.getCode() == 0 && !CollectionUtils.isEmpty(remoteData.getData())) {
				List<SysDictItem> dictList = remoteData.getData().stream().sorted(Comparator.comparing(SysDictItem::getSort)).collect(Collectors.toList());
				for (SysDictItem dictItem : dictList) {
					resultData.add(callBackUrl + "&event_type=" + dictItem.getValue());
				}
			}
		}
		return R.ok(resultData);
	}

	@Override
	public R clickTouTiaoUrl(String touTiaoUrl) {
		return R.ok(HttpUtil.get(touTiaoUrl));
	}

}
